// Kony


#include "AbilitySystem/ExecCalc/ExecCalc_Damage.h"

#include "AbilitySystemComponent.h"
#include "BaseAbilityTypes.h"
#include "BaseGameplayTags.h"
#include "AbilitySystem/BaseAbilitySystemLibrary.h"
#include "AbilitySystem/BaseAttributeSet.h"
#include "AbilitySystem/Data/CharacterClassInfo.h"
#include "Interaction/CombatInterface.h"
#include "Kismet/GameplayStatics.h"

//在cpp文件中定义的结构体 不会暴露给蓝图，所以也不需要加U前缀
struct BaseDamageStatics
{
	//声明属性捕获宏定义
	DECLARE_ATTRIBUTE_CAPTUREDEF(Armor); //护甲
	DECLARE_ATTRIBUTE_CAPTUREDEF(BlockChance); //格挡几率
	DECLARE_ATTRIBUTE_CAPTUREDEF(ArmorPenetration); //护甲穿透
	DECLARE_ATTRIBUTE_CAPTUREDEF(SpellPenetration); //法术穿透
	DECLARE_ATTRIBUTE_CAPTUREDEF(CriticalHitChance); //暴击几率
	DECLARE_ATTRIBUTE_CAPTUREDEF(CriticalHitDamage); //暴击伤害
	DECLARE_ATTRIBUTE_CAPTUREDEF(CriticalHitResistance); //暴击抵抗
	//捕获抗性宏
	DECLARE_ATTRIBUTE_CAPTUREDEF(PhysicalResistance);
	DECLARE_ATTRIBUTE_CAPTUREDEF(MagicResistance);
	DECLARE_ATTRIBUTE_CAPTUREDEF(SummonResistance);
	DECLARE_ATTRIBUTE_CAPTUREDEF(FireResistance);
	DECLARE_ATTRIBUTE_CAPTUREDEF(WaterResistance);
	DECLARE_ATTRIBUTE_CAPTUREDEF(EarthResistance);
	DECLARE_ATTRIBUTE_CAPTUREDEF(WoodResistance);
	DECLARE_ATTRIBUTE_CAPTUREDEF(GoldResistance);
	DECLARE_ATTRIBUTE_CAPTUREDEF(IceResistance);
	DECLARE_ATTRIBUTE_CAPTUREDEF(LightningResistance);
	DECLARE_ATTRIBUTE_CAPTUREDEF(WindResistance);
	DECLARE_ATTRIBUTE_CAPTUREDEF(PoisonResistance);
	DECLARE_ATTRIBUTE_CAPTUREDEF(DarkResistance);
	DECLARE_ATTRIBUTE_CAPTUREDEF(ArcaneResistance);
	// 用于存储游戏标签与属性捕获定义的映射关系，方便通过标签快速查找对应的属性捕获定义
	TMap<FGameplayTag, FGameplayEffectAttributeCaptureDefinition> TagsToCaptureDefs;
	
	BaseDamageStatics()
	{
		/************** DEFINE_ATTRIBUTE_CAPTUREDEF（捕获属性定义） **************
		 * 用于注册一个属性，以便在 GameplayEffect 中进行捕获计算
		 * 
		 * 参数说明：
		 * - UBaseAttributeSet：属性所属的 AttributeSet 类（必须继承自 UAttributeSet）
		 * - Armor            ：要捕获的属性名
		 * - Target           ：属性捕获的来源角色，可选 Source（施法者）或 Target（受术者）
		 * - false             ：是否启用快照（true 表示在效果应用前记录一次值，之后不再变化）
		 *************************************************************************/
		DEFINE_ATTRIBUTE_CAPTUREDEF(UBaseAttributeSet, Armor, Target, false);
		DEFINE_ATTRIBUTE_CAPTUREDEF(UBaseAttributeSet, BlockChance, Target, false);
		DEFINE_ATTRIBUTE_CAPTUREDEF(UBaseAttributeSet, ArmorPenetration, Source, false);
		DEFINE_ATTRIBUTE_CAPTUREDEF(UBaseAttributeSet, SpellPenetration, Source, false);
		DEFINE_ATTRIBUTE_CAPTUREDEF(UBaseAttributeSet, CriticalHitChance, Source, false);
		DEFINE_ATTRIBUTE_CAPTUREDEF(UBaseAttributeSet, CriticalHitDamage, Source, false);
		DEFINE_ATTRIBUTE_CAPTUREDEF(UBaseAttributeSet, CriticalHitResistance, Target, false);
		//捕获抗性
		DEFINE_ATTRIBUTE_CAPTUREDEF(UBaseAttributeSet, PhysicalResistance, Target, false);
		DEFINE_ATTRIBUTE_CAPTUREDEF(UBaseAttributeSet, MagicResistance, Target, false);
		DEFINE_ATTRIBUTE_CAPTUREDEF(UBaseAttributeSet, SummonResistance, Target, false);
		DEFINE_ATTRIBUTE_CAPTUREDEF(UBaseAttributeSet, FireResistance, Target, false);
		DEFINE_ATTRIBUTE_CAPTUREDEF(UBaseAttributeSet, WaterResistance, Target, false);
		DEFINE_ATTRIBUTE_CAPTUREDEF(UBaseAttributeSet, EarthResistance, Target, false);
		DEFINE_ATTRIBUTE_CAPTUREDEF(UBaseAttributeSet, WoodResistance, Target, false);
		DEFINE_ATTRIBUTE_CAPTUREDEF(UBaseAttributeSet, GoldResistance, Target, false);
		DEFINE_ATTRIBUTE_CAPTUREDEF(UBaseAttributeSet, IceResistance, Target, false);
		DEFINE_ATTRIBUTE_CAPTUREDEF(UBaseAttributeSet, LightningResistance, Target, false);
		DEFINE_ATTRIBUTE_CAPTUREDEF(UBaseAttributeSet, WindResistance, Target, false);
		DEFINE_ATTRIBUTE_CAPTUREDEF(UBaseAttributeSet, PoisonResistance, Target, false);
		DEFINE_ATTRIBUTE_CAPTUREDEF(UBaseAttributeSet, DarkResistance, Target, false);
		DEFINE_ATTRIBUTE_CAPTUREDEF(UBaseAttributeSet, ArcaneResistance, Target, false);
		//初始化游戏类型单例 避免后续DamageStatics无法获取
		FBaseGameplayTags::InitializeNativeGameplayTags();
		// 把游戏标签与属性捕获定义的映射关系添加到 TagsToCaptureDefs 中
		const FBaseGameplayTags& Tags = FBaseGameplayTags::Get();
		TagsToCaptureDefs.Add(Tags.Attributes_Secondary_Armor, ArmorDef);
		TagsToCaptureDefs.Add(Tags.Attributes_Secondary_BlockChance, BlockChanceDef);
		TagsToCaptureDefs.Add(Tags.Attributes_Secondary_ArmorPenetration, ArmorPenetrationDef);
		TagsToCaptureDefs.Add(Tags.Attributes_Secondary_SpellPenetration, SpellPenetrationDef);
		TagsToCaptureDefs.Add(Tags.Attributes_Secondary_CriticalHitChance, CriticalHitChanceDef);
		TagsToCaptureDefs.Add(Tags.Attributes_Secondary_CriticalHitDamage, CriticalHitDamageDef);
		TagsToCaptureDefs.Add(Tags.Attributes_Secondary_CriticalHitResistance, CriticalHitResistanceDef);
		//抗性
		TagsToCaptureDefs.Add(Tags.Attributes_Resistance_Physical, PhysicalResistanceDef);
		TagsToCaptureDefs.Add(Tags.Attributes_Resistance_Magic, MagicResistanceDef);
		TagsToCaptureDefs.Add(Tags.Attributes_Resistance_Summon, SummonResistanceDef);
		TagsToCaptureDefs.Add(Tags.Attributes_Resistance_Fire, FireResistanceDef);
		TagsToCaptureDefs.Add(Tags.Attributes_Resistance_Water, WaterResistanceDef);
		TagsToCaptureDefs.Add(Tags.Attributes_Resistance_Earth, EarthResistanceDef);
		TagsToCaptureDefs.Add(Tags.Attributes_Resistance_Wood, WoodResistanceDef);
		TagsToCaptureDefs.Add(Tags.Attributes_Resistance_Gold, GoldResistanceDef);
		TagsToCaptureDefs.Add(Tags.Attributes_Resistance_Ice, IceResistanceDef);
		TagsToCaptureDefs.Add(Tags.Attributes_Resistance_Lightning, LightningResistanceDef);
		TagsToCaptureDefs.Add(Tags.Attributes_Resistance_Wind, WindResistanceDef);
		TagsToCaptureDefs.Add(Tags.Attributes_Resistance_Poison, PoisonResistanceDef);
		TagsToCaptureDefs.Add(Tags.Attributes_Resistance_Dark, DarkResistanceDef);
		TagsToCaptureDefs.Add(Tags.Attributes_Resistance_Arcane, ArcaneResistanceDef);

	}
};
//创建静态变量,实例化结构体 用于重复调用
static const BaseDamageStatics& DamageStatics()
{
	static BaseDamageStatics DStatics;
	return DStatics;
}

UExecCalc_Damage::UExecCalc_Damage()
{
	// 将属性捕获定义添加到相关属性捕获列表中，以便在执行计算时能够捕获目标的属性
	RelevantAttributesToCapture.Add(DamageStatics().ArmorDef);
	RelevantAttributesToCapture.Add(DamageStatics().BlockChanceDef);
	RelevantAttributesToCapture.Add(DamageStatics().ArmorPenetrationDef);
	RelevantAttributesToCapture.Add(DamageStatics().SpellPenetrationDef);
	RelevantAttributesToCapture.Add(DamageStatics().CriticalHitChanceDef);
	RelevantAttributesToCapture.Add(DamageStatics().CriticalHitDamageDef);
	RelevantAttributesToCapture.Add(DamageStatics().CriticalHitResistanceDef);
	//捕获抗性
	RelevantAttributesToCapture.Add(DamageStatics().PhysicalResistanceDef);
	RelevantAttributesToCapture.Add(DamageStatics().MagicResistanceDef);
	RelevantAttributesToCapture.Add(DamageStatics().SummonResistanceDef);
	RelevantAttributesToCapture.Add(DamageStatics().FireResistanceDef);
	RelevantAttributesToCapture.Add(DamageStatics().WaterResistanceDef);
	RelevantAttributesToCapture.Add(DamageStatics().EarthResistanceDef);
	RelevantAttributesToCapture.Add(DamageStatics().WoodResistanceDef);
	RelevantAttributesToCapture.Add(DamageStatics().GoldResistanceDef);
	RelevantAttributesToCapture.Add(DamageStatics().IceResistanceDef);
	RelevantAttributesToCapture.Add(DamageStatics().LightningResistanceDef);
	RelevantAttributesToCapture.Add(DamageStatics().WindResistanceDef);
	RelevantAttributesToCapture.Add(DamageStatics().PoisonResistanceDef);
	RelevantAttributesToCapture.Add(DamageStatics().DarkResistanceDef);
	RelevantAttributesToCapture.Add(DamageStatics().ArcaneResistanceDef);
}
/* 重写Execute_Implementation方法，用于实现自定义的游戏效果执行计算逻辑
 * 参数ExecutionParams包含执行计算所需的所有输入数据
 * 参数OutExecutionOutput用于输出计算结果*/
void UExecCalc_Damage::Execute_Implementation(const FGameplayEffectCustomExecutionParameters& ExecutionParams,
	FGameplayEffectCustomExecutionOutput& OutExecutionOutput) const
{
	
	//获取来源能力组件和目标能力组件
	const UAbilitySystemComponent* SourceASC = ExecutionParams.GetSourceAbilitySystemComponent();
	const UAbilitySystemComponent* TargetASC = ExecutionParams.GetTargetAbilitySystemComponent();
	//获取来源和目标的Actor指针
	AActor* SourceAvatar = SourceASC ? SourceASC->GetAvatarActor() : nullptr;
	AActor* TargetAvatar = TargetASC ? TargetASC->GetAvatarActor() : nullptr;
	//施法者等级
	int32 SourcePlayerLevel = 1;
	if (SourceAvatar->Implements<UCombatInterface>())
	{
		SourcePlayerLevel = ICombatInterface::Execute_GetPlayerLevel(SourceAvatar);
	}
	//目标等级
	int32 TargetPlayerLevel = 1;
	if (TargetAvatar->Implements<UCombatInterface>())
	{
		TargetPlayerLevel = ICombatInterface::Execute_GetPlayerLevel(TargetAvatar);
	}
	//源战斗接口 和 目标战斗接口
	// ICombatInterface* SourceCombatInterface = Cast<ICombatInterface>(SourceAvatar);
	// ICombatInterface* TargetCombatInterface = Cast<ICombatInterface>(TargetAvatar);
	
	// 获取当前游戏效果规格的引用
	const FGameplayEffectSpec& Spec = ExecutionParams.GetOwningSpec();
	
	//从源和目标收集标签 Gather tags from source and target
	const FGameplayTagContainer* SourceTags = Spec.CapturedSourceTags.GetAggregatedTags();
	//目标获取
	const FGameplayTagContainer* TargetTags = Spec.CapturedTargetTags.GetAggregatedTags();
	// 创建聚合器评估参数
	FAggregatorEvaluateParameters EvaluationParameters;
	// 设置源标签
	EvaluationParameters.SourceTags = SourceTags;
	// 设置目标标签
	EvaluationParameters.TargetTags = TargetTags;
	
	//施法源目标获取角色设置的属性系数信息 和 被攻击目标获取角色设置的属性系数信息
	const UCharacterClassInfo* SourceCharacterClassInfo = UBaseAbilitySystemLibrary::GetCharacterClassInfo(SourceAvatar);
	const UCharacterClassInfo* TargetCharacterClassInfo = UBaseAbilitySystemLibrary::GetCharacterClassInfo(TargetAvatar);
	//获取游戏效果上下文句柄
	FGameplayEffectContextHandle EffectContextHandle = Spec.GetContext();
	// FGameplayEffectContext* Context = EffectContextHandle.Get();
	//把游戏效果上下文转换成自定义游戏效果上下文
	// FBaseGameplayEffectContext* BaseContext = static_cast<FBaseGameplayEffectContext*>(Context);
	//这里和之前蓝图修改器中使用 SetByCaller 是一样的效果，这个是代码调用，set by Caller Magnitude 通过tag获取伤害 
	// float Damage = Spec.GetSetByCallerMagnitude(FBaseGameplayTags::Get().Damage);
	//自定义游戏标签类
	const FBaseGameplayTags& GameplayTags = FBaseGameplayTags::Get();

	/* Debuff减益异常效果部分 */
	for (TTuple<FGameplayTag,FGameplayTag> Pair: GameplayTags.DamageTypesToDebuffs)
	{
		const FGameplayTag& DamageTypeTag = Pair.Key;
		const FGameplayTag& DebuffTag = Pair.Value;
		//通过游戏标签获取伤害类型
		float TypeDamage = Spec.GetSetByCallerMagnitude(DamageTypeTag,false,-1.f);
		//只要大于-0.5 哪怕是设置了伤害0 也是有异常效果设置的
		if (TypeDamage > -.5f)
		{
			//如果成功施加了减益效果
			//获取源目标技能设置的 触发异常几率
			const float SourceDebuffChance = Spec.GetSetByCallerMagnitude(GameplayTags.Debuff_Chance,false,-1.f);
			//目标的属性抗性
			float TargetDebuffResistance = 0.f;
			//通过异常伤害类型，获取对应的抗性标签
			const FGameplayTag ResistanceTag = GameplayTags.DamageTypesToResistances[DamageTypeTag];
			ExecutionParams.AttemptCalculateCapturedAttributeMagnitude(DamageStatics().TagsToCaptureDefs[ResistanceTag], EvaluationParameters, TargetDebuffResistance);
			//确保为整数
			TargetDebuffResistance = FMath::Max<float>(TargetDebuffResistance, 0.f);
			//通过属性抗性计算触发几率，每提升1点抗性 降低1%的触发几率
			const float EffectiveDebuffChace = SourceDebuffChance * (100 - TargetDebuffResistance) / 100;
			//创建随机值，计算是否触发异常效果
			const bool bDebuff = FMath::RandRange(1, 100) < EffectiveDebuffChace;
			if (bDebuff)
			{
				//从游戏规格中获取游戏效果上下文句柄，这里面有BaseAbilityTypes 里重写的FBaseGameplayEffectContext 数据 里面有暴击 格挡 闪避 和 各种异常效果
				FGameplayEffectContextHandle ContextHandle = Spec.GetContext();
				//设置是否成功触发异常效果
				UBaseAbilitySystemLibrary::SetIsSuccessfulDebuff(ContextHandle,true);
				//设置伤害类型
				UBaseAbilitySystemLibrary::SetDamageType(ContextHandle,DamageTypeTag);
				//获取异常效果伤害
				const float DebuffDamage = Spec.GetSetByCallerMagnitude(GameplayTags.Debuff_Damage, false,-1.f);
				//获取异常持续时间
				const float DebuffDuration = Spec.GetSetByCallerMagnitude(GameplayTags.Debuff_Duration, false,-1.f);
				//获取异常频率
				const float DebuffFrequency = Spec.GetSetByCallerMagnitude(GameplayTags.Debuff_Frequency, false,-1.f);
			
				UBaseAbilitySystemLibrary::SetDebuffDamage(ContextHandle,DebuffDamage);
				UBaseAbilitySystemLibrary::SetDebuffDuration(ContextHandle,DebuffDuration);
				UBaseAbilitySystemLibrary::SetDebuffFrequency(ContextHandle,DebuffFrequency);
			}
		}
	}
	/* 获取伤害类型和基础伤害数值部分 */
	float Damage = 0.f;
	for (const TTuple<FGameplayTag, FGameplayTag>& Pair: GameplayTags.DamageTypesToResistances)
	{
		const FGameplayTag DamageTypeTag = Pair.Key;
		const FGameplayTag ResistanceTag = Pair.Value;
		//检查该伤害类型是否已经被设置，如果没有设置则跳过
		if (Spec.SetByCallerTagMagnitudes.Contains(DamageTypeTag))
		{
			//获取伤害类型，加上false表示如果没找到对应属性的标签也不会报错，这样就不需要外层的if (Spec.SetByCallerTagMagnitudes.Contains(DamageTypeTag)) 类型判断了
			float DamageTypeValue = Spec.GetSetByCallerMagnitude(DamageTypeTag,false);
			//如果伤害小于等于0 则直接返回
			if (DamageTypeValue <= 0.f) continue;
			checkf(DamageStatics().TagsToCaptureDefs.Contains(ResistanceTag),TEXT("Resistance tag not found :[%s] in ExecCalc_Damage.cpp"), *ResistanceTag.ToString());
			const FGameplayEffectAttributeCaptureDefinition CaptureDef = DamageStatics().TagsToCaptureDefs.FindRef(ResistanceTag);
			//捕获属性抗性
			float Resistance = 0.f;
			ExecutionParams.AttemptCalculateCapturedAttributeMagnitude(CaptureDef, EvaluationParameters, Resistance);
			Resistance = FMath::Clamp<float>(Resistance, 0.f,75.f);
			
			//获取伤害抵抗系数
			// const float DamageResistanceCoefficient = GetDamageCoefficientFromCurve(TargetCharacterClassInfo,TargetCombatInterface,FName("DamageResistance"));
			//伤害计算抗性
			DamageTypeValue *= (100.f - Resistance) / 100.f;
			//判断是否是径向衰弱伤害
			if (UBaseAbilitySystemLibrary::IsRadialDamage(EffectContextHandle))
			{
				//1.在BaseCharacter中 重写 TakeDamage （受到伤害函数，这个会在调用径向伤害时 最后调用到这里）
				//2.创建广播 OnDamageDelegate , 广播 通过 TakeDamage计算的 径向伤害
				//3.绑定Lambda到受害者身上 OnDamageDelegate
				//4.调用 UGameplayStatics::ApplyRadialDamageWithFalloff ,这会调用上面角色写好的受害者身上的TakeDamage
				//5.在此Lambda表达式中写入接收到的DamageTypeValue 伤害值
				if (ICombatInterface* TargetCombatInterface = Cast<ICombatInterface>(TargetAvatar))
				{
					//绑定受到伤害广播Lambda表达式,这里 []中不能用this 而是& 因为要使用引用否则无法改变DamageTypeValue
					TargetCombatInterface->GetOnDamageSignature().AddLambda([&](float DamageAmount)
					{
						//覆盖伤害（这里是先经过上面的伤害计算，然后拿到伤害 下面调用系统计算径向伤害函数，传入伤害，计算完后会通过广播用DamageAmount回传）
						DamageTypeValue = DamageAmount;
					});
				}
				//调用系统的径向衰减伤害计算
				UGameplayStatics::ApplyRadialDamageWithFalloff(
					TargetAvatar,//目标对象
					DamageTypeValue,//当前计算好的伤害值
					0.f, //最小伤害值
					UBaseAbilitySystemLibrary::GetRadialDamageOrigin(EffectContextHandle), //半径原点
					UBaseAbilitySystemLibrary::GetRadialDamageInnerRadius(EffectContextHandle), //内半径
					UBaseAbilitySystemLibrary::GetRadialDamageOuterRadius(EffectContextHandle), //外半径
					1.f,
					UDamageType::StaticClass(),
					TArray<AActor*>(), //忽略目标数组
					SourceAvatar, //源角色对象
					nullptr
				);
			}
			Damage += DamageTypeValue;
		
		}
	}
	
	//捕获目标身上的格挡几率，如果格挡成功 伤害检少50%
	float TargetBlockChance = 0.f;
	ExecutionParams.AttemptCalculateCapturedAttributeMagnitude(DamageStatics().BlockChanceDef, EvaluationParameters, TargetBlockChance);
	TargetBlockChance = FMath::Max<float>(TargetBlockChance, 0.f); //设置如果小于0 则为0
	//判断是否格挡成功
	const bool bBlocked = FMath::RandRange(1, 100) < TargetBlockChance;
	// BaseContext->SetIsBlockedHit(bBlocked);//设置是否格挡 到游戏效果上下文
	UBaseAbilitySystemLibrary::SetIsBlockedHit(EffectContextHandle,bBlocked);//设置是否格挡 到游戏效果上下文
	Damage = bBlocked ? Damage / 2.f : Damage; //伤害减半 或者 * 0.5

	//捕获目标护甲属性
	float TargetArmor = 0.f;
	ExecutionParams.AttemptCalculateCapturedAttributeMagnitude(DamageStatics().ArmorDef, EvaluationParameters, TargetArmor);
	TargetArmor = FMath::Max<float>(TargetArmor, 0.f); 

	//捕获施法者护甲穿透属性
	float SourceArmorPenetration = 0.f;
	ExecutionParams.AttemptCalculateCapturedAttributeMagnitude(DamageStatics().ArmorPenetrationDef, EvaluationParameters, SourceArmorPenetration);
	SourceArmorPenetration = FMath::Max<float>(SourceArmorPenetration, 0.f);
	//GetDamageCoefficientFromCurve 是我封装的获取伤害系数函数用于通用获取 只需要传入源还是目标和系数名称即可
	const float ArmorPenetrationCoefficient = GetDamageCoefficientFromCurve(SourceCharacterClassInfo,SourcePlayerLevel,FName("ArmorPenetration"));

	//忽略目标护甲百分比, 部分等级越高 * 0.25f 4点元护甲就会忽略1%伤害 缩放越大 需要的穿透也越多 也可以用曲线表 
	const float EffectiveArmor = TargetArmor * (100 - SourceArmorPenetration * ArmorPenetrationCoefficient) / 100.f;
	//防御系数是从目标角色获取
	const float EffectiveArmorCoefficient = GetDamageCoefficientFromCurve(TargetCharacterClassInfo,TargetPlayerLevel,FName("EffectiveArmor"));
	Damage = Damage * (100 - EffectiveArmor * EffectiveArmorCoefficient) / 100.f;
	

	//捕获施法者护甲穿透属性
	float SourceSpellPenetration = 0.f;
	ExecutionParams.AttemptCalculateCapturedAttributeMagnitude(DamageStatics().SpellPenetrationDef, EvaluationParameters, SourceSpellPenetration);
	SourceSpellPenetration = FMath::Max<float>(SourceSpellPenetration, 0.f);
	const float SpellPenetrationCoefficient = GetDamageCoefficientFromCurve(SourceCharacterClassInfo,SourcePlayerLevel,FName("SpellPenetration"));
	//忽略目标护甲百分比, 部分等级越高 * 0.25f 4点元护甲就会忽略1%伤害 缩放越大 需要的穿透也越多 也可以用曲线表 
	const float EffectiveSpellArmor = TargetArmor * (100 - SourceSpellPenetration * SpellPenetrationCoefficient) / 100.f;
	Damage = Damage * (100 - EffectiveSpellArmor * EffectiveArmorCoefficient) / 100.f;

	//捕获施法者暴击率 爆伤 和 目标暴击抵抗
	float CriticalHitChance = 0.f;
	ExecutionParams.AttemptCalculateCapturedAttributeMagnitude(DamageStatics().CriticalHitChanceDef, EvaluationParameters, CriticalHitChance);
	CriticalHitChance = FMath::Max<float>(CriticalHitChance, 0.f);
	float CriticalHitDamage = 0.f;
	ExecutionParams.AttemptCalculateCapturedAttributeMagnitude(DamageStatics().CriticalHitDamageDef, EvaluationParameters, CriticalHitDamage);
	CriticalHitDamage = FMath::Max<float>(CriticalHitDamage, 0.f);
	float TargetCriticalHitResistance = 0.f;
	ExecutionParams.AttemptCalculateCapturedAttributeMagnitude(DamageStatics().CriticalHitResistanceDef, EvaluationParameters, TargetCriticalHitResistance);
	TargetCriticalHitResistance = FMath::Max<float>(TargetCriticalHitResistance, 0.f);
	const float CriticalHitChanceCurve = GetDamageCoefficientFromCurve(TargetCharacterClassInfo,TargetPlayerLevel,FName("EffectiveCriticalHitChance"));
 	//有效暴击几率 ， 暴击抵抗 将按照一定比例降低暴击几率
	const float EffectiveCriticalHitChance = CriticalHitChance - TargetCriticalHitResistance * CriticalHitChanceCurve;
	//判断是否暴击
	const bool bCriticalHit = FMath::RandRange(1, 100) < EffectiveCriticalHitChance;
	UBaseAbilitySystemLibrary::SetIsCriticalHit(EffectContextHandle,bCriticalHit);//设置是否暴击
	Damage = bCriticalHit ? Damage * (1 + CriticalHitDamage / 100.f) : Damage;

	
	//EGameplayModOp::Additive 加法操作
	FGameplayModifierEvaluatedData EvaluatedData(UBaseAttributeSet::GetIncomingDamageAttribute(), EGameplayModOp::Additive, Damage);
	OutExecutionOutput.AddOutputModifier(EvaluatedData);
}

float UExecCalc_Damage::GetDamageCoefficientFromCurve(
	const UCharacterClassInfo* CharacterClassInfo, 
	int32 PlayerLevel,
	FName CurveName) const
{
	if(!CharacterClassInfo || !PlayerLevel)
	{
		UE_LOG(LogTemp, Warning, TEXT("Invalid input parameters in GetDamageCoefficientFromCurve"));
		return 0.f;
	}

	if(!CharacterClassInfo->DamageCalculationCoefficients)
	{
		UE_LOG(LogTemp, Warning, TEXT("Missing DamageCalculationCoefficients in CharacterClassInfo"));
		return 0.f;
	}

	const FRealCurve* PenetrationCurve = CharacterClassInfo->DamageCalculationCoefficients->FindCurve(CurveName, FString());
	if(!PenetrationCurve)
	{
		UE_LOG(LogTemp, Warning, TEXT("Failed to find curve %s"), *CurveName.ToString());
		return 0.f;
	}

	return PenetrationCurve->Eval(PlayerLevel);
}